package com.tsy.server.manage.controller;

import com.tsy.server.manage.model.dto.DeviceDTO;
import com.tsy.server.manage.model.dto.DeviceFirmwareUpgradeDTO;
import com.tsy.server.manage.service.IDeviceService;
import com.dji.sdk.common.HttpResultResponse;
import com.dji.sdk.common.PaginationData;
import com.dji.sdk.exception.CloudSDKErrorEnum;
import com.dji.sdk.mqtt.property.PropertySetReplyResultEnum;
import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

/**
 * @author sean.zhou
 * @version 0.1
 * @date 2021/11/15
 */
@RestController
@Slf4j
@RequestMapping("${url.manage.prefix}/devices")
public class DeviceController {

    @Autowired
    private IDeviceService deviceService;

    /**
     * 获取项目下所有在线设备的拓扑列表。
     * @param projectId 项目ID
     * @return
     */
    @ApiOperation("获取项目下所有在线设备的拓扑列表")
    @GetMapping("/{project_id}/devices")
    public HttpResultResponse<List<DeviceDTO>> getDevices(@PathVariable("project_id") Long projectId) {
        List<DeviceDTO> devicesList = deviceService.getDevicesTopoForWeb(projectId);

        return HttpResultResponse.success(devicesList);
    }

    /**
     * 将设备绑定到工作空间后，设备数据仅在Web端可见。
     * @param device 设备数据
     * @param deviceSn 设备序列号
     * @return
     */
    @PostMapping("/{device_sn}/binding")
    public HttpResultResponse bindDevice(@RequestBody DeviceDTO device, @PathVariable("device_sn") String deviceSn) {
        device.setDeviceSn(deviceSn);
        boolean isUpd = deviceService.bindDevice(device);
        return isUpd ? HttpResultResponse.success() : HttpResultResponse.error();
    }

    /**
     * 根据设备序列号获取设备信息。
     * @param workspaceId 工作空间ID
     * @param deviceSn 设备序列号
     * @return
     */
    @ApiOperation("根据设备序列号获取设备信息")
    @GetMapping("/{workspace_id}/devices/{device_sn}")
    public HttpResultResponse getDevice(@PathVariable("workspace_id") String workspaceId,
                                        @PathVariable("device_sn") String deviceSn) {
        Optional<DeviceDTO> deviceOpt = deviceService.getDeviceBySn(deviceSn);
        return deviceOpt.isEmpty() ? HttpResultResponse.error("device not found.") : HttpResultResponse.success(deviceOpt.get());
    }

    /**
     * 获取某个工作空间已绑定设备的列表。
     * @param workspaceId 工作空间ID
     * @param page 页码
     * @param pageSize 分页大小
     * @return
     */
    @ApiOperation("获取工作空间已绑定设备列表")
    @GetMapping("/{workspace_id}/devices/bound")
    public HttpResultResponse<PaginationData<DeviceDTO>> getBoundDevicesWithDomain(
            @PathVariable("workspace_id") String workspaceId, Integer domain,
            @RequestParam(defaultValue = "1") Long page,
            @RequestParam(value = "page_size", defaultValue = "50") Long pageSize) {
        PaginationData<DeviceDTO> devices = deviceService.getBoundDevicesWithDomain(workspaceId, page, pageSize, domain);

        return HttpResultResponse.success(devices);
    }


    /**
     * 获取工作空间下未绑定项目的设备的列表。
     * @param workspaceId 工作空间ID
     * @return
     */
    @ApiOperation("获取工作空间下未绑定项目的飞行器")
    @GetMapping("/{workspace_id}/unbound-project/devices")
    public HttpResultResponse<List<DeviceDTO>> getunBoundProjectDevices(@PathVariable("workspace_id") String workspaceId, String query) {
        List<DeviceDTO> unboundProjectDevices = deviceService.getUnboundProjectDevices(workspaceId, query);
        return HttpResultResponse.success(unboundProjectDevices);
    }

    /**
     * 解除设备的绑定状态。
     * @param deviceSn 设备序列号
     * @return
     */
    @ApiOperation("解除设备绑定")
    @DeleteMapping("/{device_sn}/unbinding")
    public HttpResultResponse unbindingDevice(@PathVariable("device_sn") String deviceSn) {
        deviceService.unbindDevice(deviceSn);
        return HttpResultResponse.success();
    }

    /**
     * 更新设备信息。
     * @param device 设备数据
     * @param workspaceId 工作空间ID
     * @param deviceSn 设备序列号
     * @return
     */
    @ApiOperation("更新设备信息")
    @PutMapping("/{workspace_id}/devices/{device_sn}")
    public HttpResultResponse updateDevice(@RequestBody DeviceDTO device,
                                           @PathVariable("workspace_id") String workspaceId,
                                           @PathVariable("device_sn") String deviceSn) {
        device.setDeviceSn(deviceSn);
        boolean isUpd = deviceService.updateDevice(device);
        return isUpd ? HttpResultResponse.success() : HttpResultResponse.error();
    }

    /**
     * 下发离线固件升级任务。
     * @param workspaceId 工作空间ID
     * @param upgradeDTOS 升级任务参数
     * @return
     */
    @PostMapping("/{workspace_id}/devices/ota")
    public HttpResultResponse createOtaJob(@PathVariable("workspace_id") String workspaceId,
                                           @RequestBody List<DeviceFirmwareUpgradeDTO> upgradeDTOS) {
        return deviceService.createDeviceOtaJob(workspaceId, upgradeDTOS);
    }

    /**
     * 设置无人机的属性参数。
     * @param workspaceId 工作空间ID
     * @param dockSn 机场序列号
     * @param param 属性参数
     * @return
     */
    @ApiOperation("设置无人机的属性参数")
    @PutMapping("/{workspace_id}/devices/{device_sn}/property")
    public HttpResultResponse devicePropertySet(@PathVariable("workspace_id") String workspaceId,
                                                @PathVariable("device_sn") String dockSn,
                                                @RequestBody JsonNode param) {
        if (param.size() != 1) {
            return HttpResultResponse.error(CloudSDKErrorEnum.INVALID_PARAMETER);
        }

        int result = deviceService.devicePropertySet(workspaceId, dockSn, param);
        return PropertySetReplyResultEnum.SUCCESS.getResult() == result ?
                HttpResultResponse.success() : HttpResultResponse.error(result, String.valueOf(result));
    }
}